require 'tilt'
require 'erb'
require 'json'
require 'fileutils'

class GenEthContract
  def self.gen_contract(contract_name, contract_address, contract_abi)
    abi = JSON.parse(contract_abi)
    if abi.size > 0
      template = Tilt.new('lib/ethereum/templates/contract.erb')
      output = template.render(self, :contract_name => contract_name, :contract_address => contract_address, :contract_abi => abi)
      file = File.open("#{Dir.pwd}/app/contracts/#{contract_name.underscore}.rb", "w")
      file.write output
      file.close
    end
  end

  def self.gen_contract_controller(contract_name, contract_address, contract_abi)
    abi = JSON.parse(contract_abi)
    if abi.size > 0
      template = Tilt.new('lib/ethereum/templates/contract_controller.erb')
      output = template.render(self, :contract_name => contract_name, :contract_address => contract_address, :contract_abi => abi)
      file = File.open("#{Dir.pwd}/app/controllers/eth/contracts/#{contract_name.underscore}_controller.rb", "w")
      file.write output
      file.close
    end
  end

  def self.gen_contract_view(contract_name, contract_address, contract_abi)
    abi = JSON.parse(contract_abi)
    if abi.size > 0
      FileUtils.mkpath File.join("app/views/eth/contracts", contract_name.underscore)
      template = Tilt.new('lib/ethereum/templates/contract_index.html.erb')
      output = template.render(self, :contract_name => contract_name, :contract_address => contract_address, :contract_abi => abi, :tag_start => '<%', :tag_end => '%>')
      file = File.open("#{Dir.pwd}/app/views/eth/contracts/#{contract_name.underscore}/index.html.erb", "w")
      file.write output
      file.close
    end
  end

  def self.add_route(contract_name, contract_address, contract_abi)
    abis = JSON.parse(contract_abi)
    route_file = 'config/routes.rb'
    sentinel = '#ETH CONTRACT ROUTE'
    if abis.size > 0
      contract_route =  []
      contract_route << " namespace :eth do"
      contract_route << "   namespace :contracts do"
      contract_route << "     namespace :#{contract_name.underscore} do"
      contract_route << "       get 'index'"
      abis.each do |abi|
        if abi['type'] == 'function'
          contract_route << "       post '#{abi['name'].underscore}'"
        end
      end
      contract_route << "     end"
      contract_route << "   end"
      contract_route << " end"
      contract_route_str = contract_route.join("\n")

      gsub_file route_file, /(#{Regexp.escape(sentinel)})/mi do |match|
        "#{match}\n #{contract_route_str}"
      end
    end
  end

  def self.gsub_file(relative_destination, regexp, *args, &block)
    path = File.path(relative_destination)
    content = File.read(path).gsub(regexp, *args, &block)
    File.open(path, 'wb') { |file| file.write(content) }
  end
end